<?php 
namespace app\App\logic;

use plugin\saiadmin\basic\BaseLogic;
use plugin\saiadmin\exception\ApiException;
use plugin\saiadmin\utils\Helper;
use app\App\model\UserModel;
use app\App\model\CaptchaModel;
use Tinywan\Jwt\JwtToken;
use plugin\saiadmin\utils\Captcha;
use support\Request;
use Ramsey\Uuid\Uuid;
use support\Log;
use support\Cache;
use support\Facade\Config;
use plugin\saiadmin\service\storage\UploadService;
use plugin\saiadmin\utils\Arr;
use plugin\saiadmin\app\logic\system\SystemConfigLogic;

class UserLogic extends BaseLogic{

    // 验证码模型
    private $captchaModel;

   
    // 获取邮件内容，$scene 验证码场景值
    private function getMailContent($code , $scene = 1){
        $locale = getLocale();
        $email_captcha_template_zhCN = '<h1>验证码：{code}</h1><p>感谢使用</p>';
        $email_captcha_template_en = '<h1>code：{code}</h1><p>tanks for your usage</p>';

        $title_zhCN = '验证码';
        $title_en = 'code';

        return [
            'subject'=> $locale == 'en' ? $title_en: $title_zhCN ,
            'content'=> $locale == 'en' ? $email_captcha_template_en : $email_captcha_template_zhCN,
        ];
    }

    public function __construct()
    {
        $this->model = new UserModel();
        $this->captchaModel = new CaptchaModel();
    }

    // 生成图形验证码
    public function captcha()
    {
        $result = Captcha::imageCaptcha();
        return $result;
    }


    /**
     * 登录
     * @param Request $request
     * @return Response
     */
    public function login($username, $password)
    {
        // 内嵌查询
        $user_list = $this->model->where('project', $this->project)->where(function ($query) use ($username){
            if(\ValidationHelper::isEmail($username)){
                $query->where('email', $username);
            }else if(\ValidationHelper::isPhone($username)){
                $query->where('phone', $username);
            }
        })->field('id, nickname, password, salt')->select();

        if(count($user_list) > 0){
            $user = $user_list[0];
            $password_salted = md5($password . $user['salt']);
            if($password_salted == $user['password']){
                $token = $this->grandLoginToken($user['id'], $user['nickname']);
                // Log::info('登录成功', $user_list->toArray());
                return [
                    'token' => $token,
                    'user_id' => $user['id'],
                ];
            }else{
                throw new ApiException(trans('user.login_info_fail'));
            }
        }

        throw new ApiException(trans('user.user_empty'));
        return false;
    }

    // 验证码登录
    function loginCaptcha($email, $phone, $captcha){
        $type = $phone? 1: 2;
        $captchaSql = $this->captchaModel->where('content', $captcha)->where(function ($query) use ($phone, $email){
            if(hasValue($email)){
                $query->where('email', $email);
            }else if(hasValue($phone)){
                $query->where('phone', $phone);
            }
        })->where('type', $type)->where('scene', 7)->where('has_valid', 0);

        $result_captcha = $captchaSql->select();
        if(count($result_captcha) == 0){
            throw new ApiException(trans('captcha.captcha_wrong'));
        }
        forEach($result_captcha as $row){
            if($row['expiretime'] < time()){
                throw new ApiException(trans('captcha.captcha_expire'));
            }
        }

        // 改变优先级的 查询
        $user_list = $this->model->where('project', $this->project)->where(function ($query) use ($phone, $email){
            if(hasValue($email)){
                $query->where('email', $email);
            }else if(hasValue($phone)){
                $query->where('phone', $phone);
            }
        })->field('id, nickname, password, salt')->select();

        if(count($user_list) > 0){
            $user = $user_list[0];
            $token = $this->grandLoginToken($user['id'], $user['nickname']);
            $captchaSql->update(['has_valid' => 1]);
            return [
                'token' => $token,
                'user_id' => $user['id'],
            ];
        }

        throw new ApiException(trans('user.user_empty'));
        return false;
    }

    function info($userId){
        return $this->model->where('id', $userId)->where('project', $this->project)->field('id, nickname, email, phone, avatar')->find();
    }

    function changePwd($userId, $email, $phone, $password, $captcha){
        $type = $phone? 1: 2;
        $captchaSql = $this->captchaModel->where('content', $captcha)->where(function ($query) use ($phone, $email){
            if(hasValue($email)){
                $query->where('email', $email);
            }else if(hasValue($phone)){
                $query->where('phone', $phone);
            }
        })->where('type', $type)->where('scene', 2)->where('has_valid', 0);

        $result_captcha = $captchaSql->select();
        if(count($result_captcha) == 0){
            throw new ApiException(trans('captcha.captcha_wrong'));
        }
        forEach($result_captcha as $row){
            if($row['expiretime'] < time()){
                throw new ApiException(trans('captcha.captcha_expire'));
            }
        }

        if(empty($userId)){
            $user = $this->model->where(function ($query) use ($email, $phone){
                if(hasValue($email)){
                    $query->where('email', $email);
                }else if(hasValue($phone)){
                    $query->where('phone', $phone);
                }
            }) ->where('project', $this->project)->field('id, nickname, password, salt')->find();

            printSQL($this->model->where(function ($query) use ($email, $phone){
                if(hasValue($email)){
                    $query->where('email', $email);
                }else if(hasValue($phone)){
                    $query->where('phone', $phone);
                }
            }) ->where('project', $this->project)->field('id, nickname, password, salt'));

            if(empty($user['id'])){
                throw new ApiException(trans('user.user_empty'));
            }
        }else {
            $user = $this->model->where('id', $userId)->where('project', $this->project)->field('id, nickname, password, salt')->find();
            if(empty($user['id'])){
                throw new ApiException(trans('user.user_empty'));
            }
        }

        $salt = Uuid::uuid4();
        $savedPassWd = md5($password . $salt);
        // 正式改密码
        $result_flag = $this->model->update(['id' => $user['id'],'password'=> $savedPassWd,'salt'=> $salt]);
        // 验证码过期
        $captchaSql->update(['has_valid' => 1]);

        return true;
    }

    // 正式注册
    public function register($email, $phone, $password, $captcha){
        $type = $phone? 1: 2;
        $captcha_sql = $this->captchaModel->where('content', $captcha)->where(function ($query) use ($phone, $email){
            if(hasValue($email)){
                $query->where('email', $email);
            }else if(hasValue($phone)){
                $query->where('phone', $phone);
            }
        })->where('type', $type)->where('scene', 1)->where('has_valid', 0);

        $result_captcha = $captcha_sql->select();
        if(count($result_captcha) == 0){
            throw new ApiException(trans('captcha.captcha_wrong'));
        }        
        forEach($result_captcha as $row){
            if($row['expiretime'] < time()){
                throw new ApiException(trans('captcha.captcha_expire'));
            }
        }

        // 检查邮箱或手机号是否已注册
        if(hasValue($email)){
            $result_repeat = $this->model->where('email', $email)->select();
        }else if(hasValue($phone)){
            $result_repeat = $this->model->where('phone', $phone)->select();
        }
        if(count($result_repeat) > 0){
            throw new ApiException(trans('user.register_already'));
        }

        // 正式注册
        $salt = Uuid::uuid4();
        $savedPassWd = md5($password . $salt);
        $result_flag = $this->model->save([
            'group_id'=> 0,
            'nickname'=> $phone?:$email,
            'phone'=> $phone?:null,
            'email'=> $email?:null,
            'password'=> $savedPassWd,
            'salt'=> $salt,
            'project'=> $this->project,
        ]);

        if(!$result_flag){
            return [
                'success'=>false,
                'content'=> trans('user.register_fail'),
            ];
        }

        $result = $this->model->toArray();
        // 验证码过期
        $captcha_sql->update(['has_valid' => 1]);

        // 搜索注册结果并授权
        $user_id = $result['id'];
        $token = $this->grandLoginToken($user_id, $result['nickname']);
        return [
            'success'=> true,
            'content'=> [
                'token' => $token,
                'user_id' => $user_id,
            ]
        ];
    }

     public function sendCaptchaMsg($type, $scene, $email, $phone){
        $current_time = time();
        $expire_time = $current_time + config('app.app_captcha_expire'); 
        $current_time_str = formatTimestamp($current_time);
        $expire_time_str = formatTimestamp($expire_time);
        $captcha_content = GenerateRandomStr(6);


        $sendNum = 0;
        $query = $this->captchaModel->where('type', $type)->where('scene', $scene)->where('has_valid', 0)->where('expiretime', '>', $current_time);

        if (!empty($email)) {
            $sendNum = $query->where('email', $email)->count();
        } elseif (!empty($phone)) {
            $sendNum = $query->where('phone', $phone)->count();
        }

        if($sendNum > 0){
            return [
                'success'=> false,
                'content'=> trans('captcha.send_captcha_limit')
            ];
        }

        if(hasValue($email)){
            $mail_content = $this->getMailContent($captcha_content, $scene);
            Log::info('发送邮件验证码，邮箱：' . $email . "内容：", $mail_content);
            sendEmail($email, $mail_content['subject'], $mail_content['content'], $captcha_content);
        }else if(hasValue($phone)){
            sendMessage($phone, $captcha_content);
        }
        
        $success = $this->captchaModel->save([
            'content' => $captcha_content,
            'type' => $type,
            'createtime' => $current_time,
            'expiretime' => $expire_time,
            'createtime_str' => $current_time_str,
            'expiretime_str' => $expire_time_str,
            'scene' => $scene,
            'email' => $email,
            'phone' => $phone,
            'has_valid' => 0,
        ]);
        
        return [
            'success'=> true,
            'content'=> trans('common.success')
        ];
     }



    
    // 修改头像
    public function changeAvatar(){
        $data = $this->uploadImage();
        Log::info('上传数据结果：', $data);
        return $this->model->update([
            'id' => $this->userId,
            'avatar' => $data['url'],
        ])->toArray();
    }

    // 修改昵称
    public function changeNickname($newName){
        return $this->model->update([
            'id' => $this->userId,
            'nickname' => $newName,
        ]);
    }

    // 上传头像
    public function uploadImage(){
        $logic = new SystemConfigLogic();
        $uploadConfig = $logic->getGroup('upload_config');
        $type = Arr::getConfigValue($uploadConfig, 'upload_mode');
        $result = UploadService::disk($type, 'image')->uploadFile();
        $data = $result[0];
        $url = str_replace('\\', '/', $data['url']);
        $savePath = str_replace('\\', '/', $data['save_path']);
        return [
            'url' => $url,
            'path' => $savePath,
        ];
    }

    // 检查图形验证码
    public function checkCaptchaImage(Request $request){
        $code = $request->post('code', ''); //图形验证码
        $uuid = $request->post('uuid', ''); //图形验证码uuid
        if(empty($code) || empty($uuid)){
            throw new ApiException(trans('common.param_error'));
        }

        // @test 暂时隐藏图形验证码的验证
        // if (!Captcha::checkCaptcha($uuid, $code)) {
        //    throw new ApiException(trans('captcha.img_captcha_fail'));
        // }

        return true;
    }

    // 授予登录token
    public function grandLoginToken($user_id, $user_name, $type = 'App'){
        if(empty($user_id) || empty($user_name)){
            return false;
        }

        
        $expire_time = config('app.app_token_expire');
        $token = JwtToken::generateToken([
            'id' => $user_id,
            'username' => $user_name,
            'type' => $type,
            'access_exp' => $expire_time, 
            'client' => JwtToken::TOKEN_CLIENT_MOBILE, // 客户端类型
        ]);

        Cache::delete(strval($user_id));
        $cached_str = $token['token_type'].' '.$token['access_token'];
        Cache::set(strval($user_id), $cached_str, $expire_time); 
        return $token;
    }

    // 删除缓存里的token
    public function removeToken($userId){
        if(empty($userId)){
            return false;
        }
        Cache::delete(strval($userId));
        return true;
    }
}
